package com.zhiyizhen.callnumber.websocket;

import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;

import com.zhiyizhen.callnumber.common.LogUtil;
import com.zhiyizhen.callnumber.common.sp.SpConstant;
import com.zhiyizhen.callnumber.common.sp.SpUtil;
import com.zhiyizhen.callnumber.component.bean.SocketPostBean;
import com.google.gson.Gson;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;


public class WebSocketManager {
    private static final String TAG = "WebSocketManager";
//    private static final String WEB_SOCKET_URL = "ws://test.zhiyizhen.cn/ws"; // WebSocket服务器地址
    private static final String WEB_SOCKET_URL = "ws://www.zhiyizhen.cn/ws"; // WebSocket服务器地址

    // 心跳间隔时间（30秒）
    private static final long HEART_BEAT_INTERVAL = 10 * 1000;

    private static WebSocketManager instance;
    private final OkHttpClient client;
    private WebSocket webSocket;
    private boolean isConnected = false;
    private WebSocketListener listener;

    // 心跳相关
    private ScheduledExecutorService heartBeatExecutor;
    private final Handler mainHandler = new Handler(Looper.getMainLooper());

    private WebSocketManager() {
        client = new OkHttpClient.Builder()
                .pingInterval(0, TimeUnit.SECONDS) // 禁用OkHttp默认的ping机制
                .build();
    }

    public static synchronized WebSocketManager getInstance() {
        if (instance == null) {
            instance = new WebSocketManager();
        }
        LogUtil.d(TAG + "  getInstance");
        return instance;
    }

    public void setListener(WebSocketListener listener) {
        this.listener = listener;
    }

    public void connect() {
        if (isConnected) {
            LogUtil.d(TAG + "已经连接，无需重复连接");
            return;
        }

        Request request = new Request.Builder()
                .url(WEB_SOCKET_URL)
                .build();

        webSocket = client.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(@NonNull WebSocket webSocket, @NonNull Response response) {
                super.onOpen(webSocket, response);
                LogUtil.d(TAG + "连接成功");
                isConnected = true;

                sendConnectSuccessMessage();
                // 启动心跳机制
                startHeartBeat();

                if (listener != null) {
                    mainHandler.post(() -> listener.onOpen(webSocket, response));
                }
            }

            @Override
            public void onMessage(@NonNull WebSocket webSocket, @NonNull String text) {
                super.onMessage(webSocket, text);
                LogUtil.d(TAG + "收到消息: " + text);

                if (listener != null) {
                    mainHandler.post(() -> listener.onMessage(webSocket, text));
                }
            }

            @Override
            public void onMessage(@NonNull WebSocket webSocket, @NonNull ByteString bytes) {
                super.onMessage(webSocket, bytes);
                LogUtil.d(TAG + "收到二进制消息");

                if (listener != null) {
                    mainHandler.post(() -> listener.onMessage(webSocket, bytes));
                }
            }

            @Override
            public void onClosing(@NonNull WebSocket webSocket, int code, @NonNull String reason) {
                super.onClosing(webSocket, code, reason);
                LogUtil.d(TAG + "连接关闭中:code= " + code + ":" + reason);
                isConnected = false;

                // 停止心跳
                stopHeartBeat();

                if (listener != null) {
                    mainHandler.post(() -> listener.onClosing(webSocket, code, reason));
                }
            }

            @Override
            public void onClosed(@NonNull WebSocket webSocket, int code, @NonNull String reason) {
                super.onClosed(webSocket, code, reason);
                LogUtil.d(TAG + "连接已关闭: " + reason);
                isConnected = false;

                // 停止心跳
                stopHeartBeat();

                if (listener != null) {
                    mainHandler.post(() -> listener.onClosed(webSocket, code, reason));
                }

                // 尝试重连
                reconnect();
            }

            @Override
            public void onFailure(@NonNull WebSocket webSocket, @NonNull Throwable t, Response response) {
                super.onFailure(webSocket, t, response);
                LogUtil.e(TAG + "连接失败: " + t.getMessage(), t);
                isConnected = false;

                // 停止心跳
                stopHeartBeat();

                if (listener != null) {
                    mainHandler.post(() -> listener.onFailure(webSocket, t, response));
                }

                // 尝试重连
                reconnect();
            }
        });
    }

    /**
     * 启动心跳机制
     */
    private void startHeartBeat() {
        stopHeartBeat(); // 先停止已有的心跳

        heartBeatExecutor = Executors.newSingleThreadScheduledExecutor();
        // 延迟0秒开始，每HEART_BEAT_INTERVAL毫秒执行一次
        heartBeatExecutor.scheduleWithFixedDelay(this::sendHeartBeat, HEART_BEAT_INTERVAL, HEART_BEAT_INTERVAL, TimeUnit.MILLISECONDS);
        LogUtil.d(TAG + "心跳机制已启动，间隔: " + HEART_BEAT_INTERVAL + "ms");
    }

    /**
     * 停止心跳机制
     */
    private void stopHeartBeat() {
        if (heartBeatExecutor != null) {
            heartBeatExecutor.shutdownNow();
            heartBeatExecutor = null;
            LogUtil.d(TAG + "心跳机制已停止");
        }
    }

    /**
     * 发送心跳包
     */
    private void sendHeartBeat() {
        if (isConnected && webSocket != null) {
            // 这里发送自定义的心跳消息
            SocketPostBean socketPostBean = new SocketPostBean();
            socketPostBean.setCode("1002");
            socketPostBean.setMsg("心跳请求");
            SocketPostBean.DataBean dataBean = new SocketPostBean.DataBean();
            dataBean.setClinicId(SpUtil.getInt(SpConstant.CLINIC_ID, 0));
            socketPostBean.setData(dataBean);
            String heartBeatMsg = new Gson().toJson(socketPostBean);
            boolean isSent = webSocket.send(heartBeatMsg);
            LogUtil.d(TAG + "发送心跳: " + heartBeatMsg + "，发送结果: " + (isSent ? "成功" : "失败"));
        }
    }

    /**
     * 发送连接成功的消息
     */
    public void sendConnectSuccessMessage() {
        SocketPostBean socketPostBean = new SocketPostBean();
        socketPostBean.setCode("1001");
        socketPostBean.setMsg("设备上线请求");
        SocketPostBean.DataBean dataBean = new SocketPostBean.DataBean();
        dataBean.setClinicId(SpUtil.getInt(SpConstant.CLINIC_ID, 0));
        socketPostBean.setData(dataBean);
        String connectSuccessMessage = new Gson().toJson(socketPostBean);
        boolean res = sendMessage(connectSuccessMessage);
        LogUtil.d(TAG + "发送设备上线请求: " + connectSuccessMessage + "，发送结果: " + (res ? "成功" : "失败"));

    }

    /**
     * 发送消息
     */
    public boolean sendMessage(String message) {
        if (isConnected && webSocket != null) {
            return webSocket.send(message);
        }
        LogUtil.e(TAG + "发送消息失败，连接未建立");
        return false;
    }

    /**
     * 发送二进制消息
     */
    public boolean sendMessage(ByteString byteString) {
        if (isConnected && webSocket != null) {
            return webSocket.send(byteString);
        }
        LogUtil.e(TAG + "发送二进制消息失败，连接未建立");
        return false;
    }

    /**
     * 关闭连接
     */
    public void disconnect() {
        if (webSocket != null) {
            boolean isClosed = webSocket.close(1000, "主动关闭连接");
            LogUtil.d(TAG + "关闭连接: " + (isClosed ? "成功" : "失败"));
        }
        isConnected = false;
        stopHeartBeat();
    }

    /**
     * 重连机制
     */
    private void reconnect() {
        mainHandler.postDelayed(() -> {
            if (!isConnected) {
                LogUtil.d(TAG + "尝试重连...");
                connect();
            }
        }, 5000); // 5秒后尝试重连
    }

    public boolean isConnected() {
        return isConnected;
    }
}
    